#include <iostream>
#include <vector>
#include <arpa/inet.h>
#include <cstring>
#include <unistd.h>
#include <algorithm>
class SelectServer
{
private:
    int _port;
    int _listensockfd;
    fd_set _readFds;// 读事件文件描述符集合
    int _maxFd; //文件描述符最大值
    std::vector<int> _clients;//客户端套接字列表
public:
    SelectServer(int port)
        :_port(port),_listensockfd(-1),_maxFd(-1)
    {}
    void InitServer()
    {
        _listensockfd=socket(AF_INET,SOCK_STREAM,0);
        if(_listensockfd<0)
        {
            perror("TCP socket failed");
            exit(EXIT_FAILURE);
        }

        // 设置套接字选项，允许地址重用
        int opt = 1;
        setsockopt(_listensockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

        struct sockaddr_in servaddr;
        memset(&servaddr,0,sizeof(servaddr));
        servaddr.sin_family=AF_INET;
        servaddr.sin_port=htons(_port);
        servaddr.sin_addr.s_addr=INADDR_ANY;
        if(bind(_listensockfd,(struct sockaddr*)&servaddr,sizeof(servaddr))<0)
        {
            perror("TCP bind failed");
            close(_listensockfd);
            exit(EXIT_FAILURE);
        }
        if(listen(_listensockfd,10)<0)
        {
            perror("TCP listen failed");
            close(_listensockfd);
            exit(EXIT_FAILURE);
        }
        _maxFd = _listensockfd;
    }
    void Run()
    {
        while(true)
        {
            FD_ZERO(&_readFds);
            FD_SET(_listensockfd,&_readFds);
            for(int client:_clients)
            {
                FD_SET(client,&_readFds);
            }

            //更新最大文件描述符
            if(!_clients.empty())
            {
                _maxFd=std::max(_listensockfd,*std::max_element(_clients.begin(),_clients.end()));
            }
            else{
                _maxFd=_listensockfd;
            }

            //使用select等待事件
            int activities=select(_maxFd+1,&_readFds,nullptr,nullptr,nullptr);
            if(activities<0)
            {
                perror("Select error");
                break;
            }

            //到这一定有事件发生，处理事件
            if(FD_ISSET(_listensockfd,&_readFds))
            {
                //处理新连接
                HandleNewConnection();
            }

            //处理客户端套接字上的数据
            for(auto it=_clients.begin();it!=_clients.end();)
            {
                int clientSock=*it;
                if(FD_ISSET(clientSock,&_readFds))
                {
                    //处理普通套接字上的数据
                    if(!HandleClient(clientSock))
                    {
                        //如果客户端断开连接，移除套接字
                        it=_clients.erase(it);
                        continue;
                    }
                }
                ++it;
            }
        }
    }
private:
    void HandleNewConnection()
    {
        struct sockaddr_in cliaddr;
        socklen_t len=sizeof(cliaddr);
        int clientSock=::accept(_listensockfd,(struct sockaddr*)&cliaddr,&len);
        if(clientSock<0)
        {
            perror("TCP accept failed");
            return;
        }
        std::cout<<"new connection from " <<inet_ntoa(cliaddr.sin_addr)<<":"<<ntohs(cliaddr.sin_port)<<std::endl;
        _clients.push_back(clientSock);
    }
    bool HandleClient(int clientSock)
    {
        char buffer[1024]={0};
        size_t bytesRead=read(clientSock,buffer,sizeof(buffer)-1);
        if(bytesRead<=0)
        {
            //客户端断开连接
            std::cout << "Client disconnected: " << clientSock << std::endl;
            close(clientSock);
            return false;
        }
        buffer[bytesRead]='\0';
        std::cout << "Received from client " << clientSock << ": " << buffer;

        // 回显数据给客户端
        write(clientSock, buffer, bytesRead);
        return true;
    }
};